#include <iostream>
#include <thread>

/**
 * @brief 启动线程，执行回调逻辑
 */
void start()
{
    { // 启动线程
        auto print = [](const std::string& str)
        {
            std::cout << str << std::endl;
        };

        std::thread t1{print , "Hello Concurrent"};
        t1.join(); // 等待线程
    }
}

/**
 * @brief 普通函数传递
 */
void OrdinaryFunction(const std::string& str)
{
    std::cout << " Ordinary function" << str << std::endl;
}

class FunClass
{
public:
    void operator() (const std::string& str) const
    {
        std::cout << "Imitation Function" << str << std::endl;
    }
};

void Callback()
{
    std::string strVar{"Hello"};

    std::jthread t2{OrdinaryFunction , "Hello Ordinary Function"}; // 普通函数传递
    std::jthread t3{[&strVar](const std::string& str)
    {
        std::cout << strVar << " " << str << std::endl;
    } , "Lambda"}; // lambda传递
    std::jthread t4{FunClass() , "Hello"}; // 仿函数
}

struct FunStruct
{
    explicit FunStruct(int& n_var)
        : _nVar(n_var){}

    void operator() () const
    {
        for (int i = 0; i < 3; ++i)
        {
            _nVar = i;
            std::cout << "var:" << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }

private:
    int& _nVar;
};

/**
 * @brief 分离线程
 */
void Detach()
{
    int nLocalVar{}; // 局部变量
    FunStruct fun{nLocalVar};
    std::thread t5{fun};
    t5.detach(); // 访问局部变量，局部变量被回收
}

/**
 * @brief 线程异常
 */
void expect()
{
    int nLocalVar{};
    FunStruct fun{nLocalVar};
    std::thread t6{fun};
    try
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    catch (std::exception& e)
    {
        t6.join();
        throw;
    } // 主线程出现异常的时候，保证子线程资源被正确回收
}

/**
 * @brief 守护线程，利用RAII技术，保证对象析构的时候等待线程运行结束
 */
class GuardThread
{
public:
    explicit GuardThread(std::thread& thread)
        : _thread(thread){}

    /**
     * @brief 禁用拷贝操作，防止多重管理同一个线程对象
     * @param other
     */
    GuardThread(const GuardThread& other) = delete;

    GuardThread& operator=(const GuardThread& other) = delete;

    ~GuardThread()
    {
        if (_thread.joinable())
        {
            _thread.join();
        }
    }

private:
    std::thread& _thread;
};

int main()
{
    // start();
    // Callback();
    {
        Detach();
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    return 0;
}
